package com.mc.fastkit.log

import com.mc.fastkit.ext.createDir
import com.mc.fastkit.ext.listAll
import com.mc.fastkit.ext.toString
import com.mc.fastkit.utils.DateUtils
import com.mc.fastkit.utils.StackTraceUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
import java.util.Date
import kotlin.concurrent.thread
import kotlin.coroutines.EmptyCoroutineContext

/**
 * 日志文件管理器
 * @author: MasterChan
 * @date: 2023-02-21 10:08:36
 */
class LogManager : ILogManager {

    private fun obtainLogFile(): File {
        File(getConfig().logDir).createDir()
        val path = "${getConfig().logDir}/${Date().toString("yyyyMMdd")}.${getConfig().extension}"
        return File(path)
    }

    override fun save(log: String) {
        //切换线程后找不到堆栈，在线程外获取
        val element = StackTraceUtils.getTargetStackTraceElement(LogUtils::class.java)
        CoroutineScope(EmptyCoroutineContext).launch(Dispatchers.IO) {
            try {
                val header = Date().toString("yyyy-MM-dd HH:mm:ss:SS ")
                var content: String
                if (element == null) {
                    content = "$header\n$log\n"
                } else {
                    val className = element.className.substringAfterLast(".")
                    val stack = "$className.${element.methodName}(${element.fileName}:${element.lineNumber})"
                    content = "$header $stack\n$log"
                    if (!log.endsWith("\n") || !log.endsWith("\n\r")) content += "\n"
                }
                obtainLogFile().appendText(content)
            } catch (t: Throwable) {
                t.printStackTrace()
            }
        }
    }

    @Synchronized
    override fun deleteOverdue() {
        thread(name = "deleteOverdue") {
            val logDir = File(getConfig().logDir)
            kotlin.runCatching {
                if (!logDir.exists()) return@runCatching
                logDir.listAll().forEach {
                    if (DateUtils.dayDiff(Date(it.lastModified()), Date()) > getConfig().saveDays) {
                        it.delete()
                    }
                }
            }
        }
    }
}